package com.zzdn.mqtool.utils;

import com.ibm.mq.*;
import com.zzdn.mqtool.entity.MQConfig;
import org.apache.commons.lang.StringUtils;

import java.util.Hashtable;

public class MQManager {
    private MQQueueManager qMgr = null;

    public MQManager(MQConfig mqConfig) throws Exception {
        init(mqConfig);
    }

    public MQQueueManager getManager(){
        return qMgr;
    }

    public void init(MQConfig mqConfig){
        try {
            if(qMgr != null){
                qMgr.disconnect();
            }
            Hashtable<String, Object> properties = new Hashtable<String, Object>();
            properties.put(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES);
            properties.put(MQC.HOST_NAME_PROPERTY, mqConfig.getMqServerURL());
            properties.put(MQC.PORT_PROPERTY, new Integer(mqConfig.getMqServerPort()));
            String serverChannel = null;
            if(!StringUtils.isEmpty(mqConfig.getMqServerChannel())){
                serverChannel = mqConfig.getMqServerChannel();
            } else {

                serverChannel = "SYSTEM.DEF.SVRCONN"; // 采用默认的服务器传输通道
            }
            properties.put(MQC.CHANNEL_PROPERTY, serverChannel);
            properties.put(MQC.CCSID_PROPERTY, new Integer(1381));
            qMgr = new MQQueueManager(mqConfig.getMqServerName(), properties);
        } catch (Exception e) {
            throw new RuntimeException("无法连接到MQ，请检查网络和MQ配置:", e);
        }
    }

    public void disconnect(){
        try {
            qMgr.disconnect();
        } catch (MQException e) {
            throw new RuntimeException("断开MQ连接异常:", e);
        }
    }

    public boolean sendMsg(String remoteQueue, String messageId,
                           String correlationId, String messageContent, Integer priority) {
        boolean flag = false;
        MQQueue remoteMQQueue = null;
        try {
            MQMessage mqMessage = new MQMessage();// 要写入队列的消息
            // msg.format=MQC.MQFMT_STRING;
            mqMessage.encoding = 546;
            mqMessage.characterSet = 1381;
            if(priority != null){
                mqMessage.priority = priority;
            } else {
                mqMessage.priority = 4;
            }
            mqMessage.expiry = -1; // 设置消息用不过期
            mqMessage.messageId = (messageId.getBytes());
            mqMessage.correlationId = (correlationId.getBytes());
            if(messageContent != null){
                mqMessage.write(messageContent.getBytes("GBK"));
            }
            remoteMQQueue = this.getRemoteQueue(qMgr, remoteQueue);
            remoteMQQueue.put(mqMessage);// 将消息放入队列
            flag = true;
        } catch (Exception e) {
            throw new RuntimeException("向MQ发送消息失败:", e);
        } finally{
            if (remoteMQQueue != null) {
                try {
                    remoteMQQueue.close();
                } catch (MQException e) {
                    throw new RuntimeException("关闭MQ远程队列异常:", e);
                }
            }
        }
        return flag;
    }


    public MQMessage getMsg(String localQueue, String correlationId, int waitInterval){
		/*if(!isAllow(qMgr, localQueue)){
			return null;
		}*/
        MQQueue localMQQueue = null;
        try {
            // 建立连接
            localMQQueue = this.getLocalQueue(qMgr, localQueue);
            MQGetMessageOptions gmo = new MQGetMessageOptions();
            gmo.options = gmo.options + MQC.MQGMO_WAIT;
//			gmo.options = gmo.options + MQC.MQGMO_FAIL_IF_QUIESCING;
            if (correlationId != null) {
                gmo.matchOptions = MQC.MQMO_MATCH_CORREL_ID;
            }
            gmo.waitInterval = waitInterval;
            MQMessage mqMessage = new MQMessage();// 要写入队列的消息
            if (correlationId != null) {
                mqMessage.correlationId = correlationId.getBytes();
            }
            localMQQueue.get(mqMessage, gmo);// 从队列取出消息
            return mqMessage;
        } catch (MQException mqe) {
            if (mqe.reasonCode == 2033) {
                // 忽略数据MQ队列为空的情况
                return null;
            } else {
                throw new RuntimeException("从MQ接收消息异常:", mqe);
            }
        } catch (Exception e) {
            throw new RuntimeException("从MQ接收消息失败:", e);
        } finally{
            if (localMQQueue != null) {
                try {
                    localMQQueue.close();// 关闭本地队列
                } catch (MQException e) {
                    throw new RuntimeException("关闭MQ本地队列异常:", e);
                }
            }
        }
    }


    public MQQueue getLocalQueue(MQQueueManager qMgr, String localQueue) throws Exception {
		/*int openOptionsReceive = MQC.MQOO_FAIL_IF_QUIESCING | MQC.MQOO_OUTPUT
				| MQC.MQOO_INPUT_AS_Q_DEF | MQC.MQOO_INQUIRE;*/
        int openOptionsReceive =MQC.MQGMO_FAIL_IF_QUIESCING|MQC.MQOO_INPUT_AS_Q_DEF;
        // int openOptionsReceive=MQC.MQGMO_SYNCPOINT|MQC.MQGMO_WAIT|MQC.MQGMO_FAIL_IF_QUIESCING;

        //setversion---mqmdversion2;
        //MQC.MQOO_BROWSE,MQC.MQGMO_FAIL_IF_QUIESCING 浏览模式
        //MQC.MQOO_INPUT_AS_Q_DEF
        //MQC.MQC.MQGMO_FAIL_IF_QUIESCING
        MQQueue local_queue = qMgr.accessQueue(localQueue, openOptionsReceive);// 本地接口（接收）*/
        return local_queue;
    }

    public MQQueue getRemoteQueue(MQQueueManager qMgr, String remoteQueue) throws Exception {
        int openOptionsPut = MQC.MQOO_FAIL_IF_QUIESCING | MQC.MQOO_OUTPUT
                | MQC.MQOO_INQUIRE;
        MQQueue remote_queue = qMgr.accessQueue(remoteQueue, openOptionsPut);// 本地远程接口（发送）
        return remote_queue;
    }

}
